package com.ksyun.ks3.exception;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.ksyun.ks3.util.Constants;
import com.ksyun.ks3.util.ResponseUtils;
import com.ksyun.ks3.util.StringUtils;

import android.util.Log;

import okhttp3.Headers;

public class Ks3ServiceException extends Exception {
    /**
     * http 状态码
     */
    private int statusCode;
    /**
     * 返回的http头信息
     */
    private Map<String, String> headers;
    /**
     * 响应体
     */
    private String response;
    /**
     * 错误码
     */
    private String errorCode;
    /**
     * 错误信息
     */
    private String errorMessage;
    /**
     * 用户请求的资源
     */
    private String resource;
    /**
     * 用户请求的id
     */
    private String requestId;

    public Ks3ServiceException(int statusCode, Headers responseHeaders, byte[] response) {
        this.statusCode = statusCode;
        this.headers = ResponseUtils.parseResponseHeaders(responseHeaders);
        this.parseServerError(response);
        if (response != null) {
            this.response = new String(response);
            Log.e(Constants.GLOBLE_LOG_TAG, new String(response));
        } else {
            this.response = "";
            Log.e(Constants.GLOBLE_LOG_TAG, "response string is null");
        }
    }

    private void parseServerError(byte[] response) {
        if (response != null && !StringUtils.isBlank(new String(response))) {
            XmlPullParserFactory factory;
            try {
                factory = XmlPullParserFactory.newInstance();
                XmlPullParser parse = factory.newPullParser();
                parse.setInput(new ByteArrayInputStream(response), "UTF-8");
                int eventType = parse.getEventType();
                while (XmlPullParser.END_DOCUMENT != eventType) {
                    String nodeName = parse.getName();
                    switch (eventType) {
                        case XmlPullParser.START_DOCUMENT:
                            break;
                        case XmlPullParser.END_DOCUMENT:
                            break;
                        case XmlPullParser.START_TAG:
                            if (nodeName.equalsIgnoreCase("Code")) {
                                this.errorCode = parse.nextText();
                            }
                            if (nodeName.equalsIgnoreCase("Message")) {
                                this.errorMessage = parse.nextText();
                            }
                            if (nodeName.equalsIgnoreCase("Resource")) {
                                this.resource = parse.nextText();
                            }
                            if (nodeName.equalsIgnoreCase("RequestId")) {
                                this.requestId = parse.nextText();
                            }
                            break;
                        case XmlPullParser.END_TAG:
                            break;
                        case XmlPullParser.TEXT:
                            break;
                        default:
                            break;
                    }
                    eventType = parse.next();
                }
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // Head请求没有body，需要从header中获取requestId
        if (StringUtils.isBlank(this.requestId)) {
            this.requestId = this.headers.get("x-kss-request-id");
        }
        if (StringUtils.isBlank(this.getErrorCode()) || "unknow".equals(this.getErrorCode()) || "unknown".equalsIgnoreCase(this.getErrorCode())) {
            if (this.statusCode == 400) {
                this.errorCode = "InvalidArgument";
            } else if (this.statusCode == 403) {
                this.errorCode = "AccessDenied";
            } else if (this.statusCode == 404) {
                this.errorCode = "NotFound";
            } else if (this.statusCode == 405) {
                this.errorCode = "MethodNotAllowed";
            }
        }
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public String getResource() {
        return resource;
    }

    public void setResource(String resource) {
        this.resource = resource;
    }

    public String getRequestId() {
        return requestId;
    }

    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(Map<String, String> headers) {
        this.headers = headers;
    }

    public String getResponse() {
        return response;
    }

    public void setResponse(String response) {
        this.response = response;
    }

    @Override
    public String getMessage() {
        return "[RequestId:" + this.requestId
                + ", Resource:" + this.resource
                + ", Status code:" + this.statusCode
                + ", Error code:" + this.errorCode
                + ", Error message:" + this.errorMessage
                + "]";
    }
}
